﻿using AiBLSmartEdu.Module.AIMedicalAssistant.API.DTOs;
using AutoMapper;
using ChromaDB.Client;
using ChromaDB.Client.Models;
using DocumentFormat.OpenXml.Office.SpreadSheetML.Y2023.MsForms;
using Domain.Entities;
using FrameworkCore.DI;
using FrameworkCore.Extensions;
using FrameworkCore.Helpers;
using FrameworkCore.Interfaces;
using FrameworkCore.Models;
using FrameworkCore.Repositories;
using Polly;
using System.Net.Http;
using System.Text;

#nullable disable

namespace AiBLSmartEdu.Module.AIMedicalAssistant.API.Services
{
    /// <summary>
    /// AI+就医助手咨询服务
    /// </summary>
    public class MedicalAssistantService : IScopedDependency
    {
        private readonly KnowledgeBaseService _knowledgeBaseService;
        private readonly IRepository<MedicalQuestionAnswerPairs> _medicalQuestionAnswersRepository;
        private readonly IMapper _mapper;
        private readonly EmbeddingGenerator _embeddingGenerator;
        private readonly OllamaService _ollamaService;
        private readonly ChromaClientService _chromaClientService;
        private readonly ICurrentUserService _currentUserService;

        public MedicalAssistantService(
            KnowledgeBaseService knowledgeBaseService,
            IRepository<MedicalQuestionAnswerPairs> medicalQuestionAnswersRepository,
            IMapper mapper,
            EmbeddingGenerator embeddingGenerator,
            OllamaService ollamaService,
            ChromaClientService chromaClientService,
            ICurrentUserService currentUserService)
        {
            _knowledgeBaseService = knowledgeBaseService;
            _medicalQuestionAnswersRepository = medicalQuestionAnswersRepository;
            _mapper = mapper;
            _embeddingGenerator = embeddingGenerator;
            _ollamaService = ollamaService;
            _chromaClientService = chromaClientService;
            _currentUserService = currentUserService;
        }

        /// <summary>
        /// 发起提问
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task CreateAsync(MedicalQuestionAnswerPairsCreateInputModel model)
        {
            ExceptionHelper.ThrowIfNullOrWhiteSpace(model.Question, $"问题不能为空：{nameof(model.Question)}");
            await _knowledgeBaseService.InitializeKnowledgeBaseAsync(model.KnowledgeBaseId);
            await _medicalQuestionAnswersRepository.InsertAsync(new MedicalQuestionAnswerPairs 
            {
                Question = model.Question,
                DialogueId = model.DialogueId,
                KnowledgeBaseId = model.KnowledgeBaseId,
            });

            //const int embedDimension = 384; // 与集合维度一致
            //const int maxRetries = 3;
            //var collectionClient = _chromaClientService.GetCollectionClient(model.KnowledgeBaseId.ToString());
            
            //// 1. 生成问题嵌入（实际应调用模型API）
            //var queryEmbedding = await _embeddingGenerator.GenerateEmbeddingAsync(model.Question, embedDimension);
            //var queryMemory = new ReadOnlyMemory<float>(queryEmbedding);

            //// 2. 执行向量查询
            //var results = await Policy
            //    .Handle<HttpRequestException>()
            //    .RetryAsync(maxRetries)
            //    .ExecuteAsync(async () =>
            //        await collectionClient.Query(
            //            queryEmbeddings: new List<ReadOnlyMemory<float>> { queryMemory },
            //            nResults: 100, // 增加返回结果数量
            //            include: ChromaQueryInclude.Metadatas | ChromaQueryInclude.Distances
            //        ));

            //// 3. 构建优化后的上下文
            //var context = BuildContext(results, maxLength: 100000);

            //// 4. 生成增强型Prompt
            //var prompt = $$"""
            //    请基于以下上下文用中文回答问题，遵循以下规则：
            //    1. 如果上下文无关，回答"该问题超出知识范围"
            //    2. 保持回答专业简洁
            //    3. 使用Markdown格式

            //    上下文：
            //    {{context}}

            //    问题：{{model.Question}}
            //    答案：
            //    """;

            //// 5. 获取模型回答
            //var aa = await _ollamaService.GenerateResponseAsync(_currentUserService.UserId, prompt, "deepseek-r1");

            //string BuildContext(List<List<ChromaCollectionQueryEntry>> results, int maxLength)
            //{
            //    var context = new StringBuilder();
            //    var entries = results.FirstOrDefault()
            //        ?.OrderBy(e => e.Distance) // 按相似度排序
            //        ?? Enumerable.Empty<ChromaCollectionQueryEntry>();

            //    foreach (var entry in entries)
            //    {
            //        var content = entry.Metadata?
            //            .GetValueOrDefault("content")?
            //            .ToString()?
            //            .Trim();

            //        if (!string.IsNullOrEmpty(content))
            //        {
            //            // 检查是否还有空间添加新内容
            //            if (context.Length + content.Length + 2 > maxLength) // +2 for "\n"
            //            {
            //                // 如果剩余空间不足，检查是否至少有一个完整段落
            //                if (context.Length > 0) break;
            //            }

            //            context.AppendLine(content); // 直接添加内容，不加破折号
            //        }
            //    }
            //    return context.ToString();
            //}
        }

        /// <summary>
        /// 分页查询
        /// </summary>
        /// <param name="filter">分页输入模型</param>
        /// <returns></returns>
        public async Task<PageResult<MedicalQuestionAnswerPairsOutputModel>> PageAsync(MedicalQuestionAnswerPairsPaginationFilter filter)
        {
            return (await _medicalQuestionAnswersRepository.GetOrderedQueryable(query =>
            {
                return query.OrderByDescending(o => o.Id)
                .WhereIf(filter.KnowledgeBaseId.HasValue && filter.KnowledgeBaseId.Value > 0
                      && filter.DialogueId.HasValue && filter.DialogueId.Value > 0,
                      x => x.KnowledgeBaseId == filter.KnowledgeBaseId.Value && x.DialogueId == filter.DialogueId.Value)
                .WhereIf(!filter.Keyword.IsNullOrWhiteSpace(), x => x.Question.Contains(filter.Keyword));

            }, filter).ProjectToPaginatedDataAsync<MedicalQuestionAnswerPairs, MedicalQuestionAnswerPairsOutputModel>(
                filter.PageNumber,
                filter.PageSize,
                _mapper.ConfigurationProvider
            )).ToPageList();
        }

        /// <summary>
        /// 修改答案
        /// </summary>
        /// <param name="userId">用户ID</param>
        /// <param name="question">问题</param>
        /// <param name="answer">答案</param>
        /// <param name="knowledgeBaseId">知识库</param>
        /// <param name="DialogueId">对话</param>
        /// <returns></returns>
        public async Task UpdateAnswerAsync(string userId, string question, string answer,string knowledgeBaseId, string DialogueId)
        {
            long.TryParse(knowledgeBaseId, out long knowledgeBaseLongId);
            long.TryParse(DialogueId, out long DialogueLongId);

            await _medicalQuestionAnswersRepository.UpdateAsync(x =>
                x.SetProperty(p => p.Answer, p => answer),
                 w => w.CreatedBy == userId
                 && w.Question == question
                 && string.IsNullOrWhiteSpace(w.Answer)
                 && w.KnowledgeBaseId == knowledgeBaseLongId
                 && w.DialogueId == DialogueLongId);
        }
    }
}
